home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / magazi~1 / 354 / twarp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-01-03  |  26.0 KB  |  813 lines

  1. /* 
  2.  * MEGA-TRANS-WARP DRIVE
  3.  *
  4.  * By: Dan Moore and Dave Small. Copyright 1987, 1988
  5.  *
  6.  * This TSR goes in your AUTO folder. After it is run, any large access to
  7.  * the floppy disk drive goes at twice the speed it used to (maybe more
  8.  * on double sided drives). You'll notice it on big copies. 
  9.  *
  10.  * 0.5: Found Atari's seek-with-verify is done on same-track accesses. Ugly.
  11.  * This causes single sector reads to miss a complete spin. Ugly. Forced
  12.  * us to call ROMs directly to bypass that seek. -dlm, dms
  13.  *
  14.  * 1: Original version -- there's a bug in it. Buffer problem. -- dlm
  15.  *
  16.  * 2: Found that we need to 0-base sector # before multiplying by 512 to
  17.  * get buffer address, or we land 512 too far down. Added some
  18.  * debug code to find out what was going on. -- dms
  19.  *
  20.  * 3: Changed for 9/10 sec disks.. also, gotta add 2 (modulus) if twistered.
  21.  *   I analyzed what happens on a twistered disk, and find that the change
  22.  *   is not really that bad (2 extra sectors spin by each spin). So, no
  23.  *   need to change it. Cleaned up, commented. -- dms
  24.  *
  25.  *   Added TSR sign-in page.
  26.  *
  27.  * 4: Misc. clean up to produce the work of ART you are now examining! 
  28.  *    Also added a check for the right cut of the TOS ROM.  (It wouldn't
  29.  *    be nice to jump off to never never land.) -- dlm
  30.  *
  31.  * 5: 06/20/88 (1 year after above stuff) -- taught it about the "new"
  32.  *    (well new since we wrote this) blitter ROMs in the Megas.  This
  33.  *    is the new improved Mega-Trans-Warp Drive for your ST. -- dms & dlm
  34.  *
  35.  * 5.1: 07/08/88 (2 weeks after last comment --- wow we can tell time)
  36.  *    finish fixing the mega rom version.  -- dlm & dms
  37.  */
  38.  
  39. #include <portab.h>
  40. #include <osbind.h>
  41.  
  42. /* misc defines */
  43. #define TRUE   1
  44. #define FALSE  0
  45. #define RETRY  0x00010000
  46. #define void   /**/
  47.  
  48. #define LOADADR 0        /* print load address, bigger code tho. */
  49.  
  50. #define   low8bits(x) ((x) & 0xff) 
  51.  
  52. #define   puts(str) Cconws(str)         /* I can remember puts, but Cconws? */
  53.  
  54. /* 
  55.  * defines for OS version test
  56.  */
  57. #define BUILDDATE   0x11201985L         /* build date for current ROM       */
  58. #define MEGDATE     0x04221987L        /* build date for more current ROM  */
  59. #define DATEADR     0x00fc0018L         /* location of date in OS ROM       */
  60.  
  61. /*
  62.  * Error codes
  63.  */
  64. #define   OK                  0         
  65. #define   DRIVE_NOT_READY     (-2)
  66. #define   MEDIA_CHANGE        (-14)
  67. #define   BAD_SECTORS         (-16)     
  68.  
  69. #define   CRITICAL_RETRY 0x00010000L         /* "retry" return code */
  70.  
  71. /*
  72.  * media change status
  73.  */
  74. #define   SAFE      0
  75. #define   UNSURE    1    
  76. #define   CHANGED   2    
  77.  
  78. /* typedefs to make declarations easier */
  79. typedef LONG (*L_FUNC)();     /* pointer to function returning a long */
  80. typedef WORD (*W_FUNC)();     /* pointer to function retruning a word */
  81.  
  82. /* misc. global work variables */
  83. L_FUNC   sys_rwabs;                       /* old rwabs routine.             */
  84. L_FUNC  *rwvect = (L_FUNC *) 0x476;       /* pointer to current rwabs       */
  85. L_FUNC  *critic = (L_FUNC *) 0x404L;      /* system critical error handler  */
  86.  
  87. /* 
  88.  * We have to directly call ROM routines out of floprw, or recode them here.
  89.  * We chose to call them. 
  90.  */
  91.  
  92. #define  old_chkm        0xfc1000L
  93. #define  new_chkm        0xfc11e4L
  94.  
  95. L_FUNC   chkmedia;         /* pointer to ROM routine         */
  96.  
  97. /*
  98.  * BPB structure
  99.  */
  100. struct bpb {
  101.     WORD recsiz,             /* physical sector size in bytes */
  102.         clsiz,              /* cluster size in sectors */
  103.         clsizb,             /* cluster size in bytes */
  104.         rdlen,              /* root directory length in sectors */
  105.         fsiz,               /* FAT size in sectors */
  106.         fatrec,             /* sector# of 1st sector of 2nd FAT */
  107.         datrec,             /* sector# of 1st data sector */
  108.         numcl,              /* number of data clusters on disk */
  109.         bflags;             /* various flags */
  110. };
  111.  
  112. /*
  113.  * "Device State Block"
  114.  * as defined by us.
  115.  * The DSB is used by drivers to hold a device's state.
  116.  * Most devices require a pointer to this beastie as a parameter
  117.  * in their calls.
  118.  */
  119. struct dsb {
  120.     struct bpb b;       /* GEMDOS' BPB                 */
  121.     WORD dntracks,      /* #tracks (cylinders) on dev  */
  122.         dnsides,       /* #sides per cylinder         */
  123.         dspc,          /* #sectors/cylinder           */
  124.         dspt,          /* #sectors/track              */
  125.         dhidden;       /* #hidden tracks              */
  126.     char dserial[3];    /* 24-bit volume serial number */
  127. } *dsbtab;
  128.  
  129. #define old_dsbtab    0x4dceL
  130. #define new_dsbtab    0x7570L
  131.  
  132. /*
  133.  * the following are misc control variables used by the ROM routines.
  134.  * one reason we "stole" the ROM routines and variables is to avoid
  135.  * having to rewrite the VBLANK routines that change some of these
  136.  * variables.  (The VBLANK routine checks for disk insertion/removal by
  137.  * watching the write protect status of the disk.  That's where media
  138.  * "UNSURE" errors come from.)
  139.  */
  140. WORD *fverify  = (WORD *) 0x0444L;    /* system floppy table */
  141. BYTE *diskmode = (BYTE *) 0x4db8L;
  142. BYTE *diskbuf  = (BYTE *) 0x167aL;
  143. WORD *nflops   = (WORD *) 0x04a6L;    /* number of floppies (0-2) */
  144.  
  145. #define old_diskm    0x4db8L
  146. #define new_diskm    0x755aL
  147.  
  148. #define old_diskbuf    0x167aL
  149. #define new_diskbuf    0x16daL
  150.  
  151. WORD  all_cool;                      /* true means good ROM rev */
  152. WORD  newer_roms;             /* true for the new ROMs */
  153.  
  154. /*
  155.  * macros to handle selection of the correct floppy i/o patch routine
  156.  * based on the rom version we are running under.
  157.  * also set the ret value for the "outside" routine that calls us.
  158.  */
  159. #define do_read(a,b,c,d,e,f,g)    {                     \
  160.         if (newer_roms)                        \
  161.             ret = meg_floprd((a),(b),(c),(d),(e),(f),(g));    \
  162.         else                            \
  163.             ret = our_floprd((a),(b),(c),(d),(e),(f),(g));    \
  164.                 }
  165.  
  166. #define do_write(a,b,c,d,e,f,g)    {                     \
  167.         if (newer_roms)                        \
  168.             ret = meg_flopwr((a),(b),(c),(d),(e),(f),(g));    \
  169.         else                            \
  170.             ret = our_flopwr((a),(b),(c),(d),(e),(f),(g));    \
  171.                 }
  172.  
  173. extern saveA4(), exit();
  174. asm {
  175. exit:        ; just to fool the linker and prevent the inclusion
  176.         ; of unneeded (and unwanted) library routines
  177.  
  178. saveA4:   dc.l 0    ; pointer to global variables
  179.             ; in program segment so rwabs can get it
  180. }
  181.  
  182.  
  183. extern bytecpy();
  184. asm {
  185.     ; bytecpy(source, dest)
  186.     ; one byte at a time copy, for non-aligned moves.  SLOW!!!!!!
  187. bytecpy:
  188.     move.l  #511,  D0        ; count - 1 
  189.     movea.l 4(A7), A0        ; source
  190.     movea.l 8(A7), A1        ; dest
  191.  
  192. loop:
  193.     move.b  (A0)+, (A1)+     ; move a WHOLE byte (as opposed to a nybble)
  194.     dbf     D0, loop
  195.  
  196.     rts                      ; all done.
  197. }
  198.  
  199. /*
  200.  * Convert a low high (8086 style) number to high low (68K) style.
  201.  */
  202. int swapint(loc)
  203. char *loc;
  204. {
  205.     return (low8bits(*(loc+1)) << 8) | low8bits(*loc);
  206. }
  207.  
  208. /* 
  209.  * due to a major stupidity in the ST BIOS, we have to clone the
  210.  * first few lines of floprd & flopwr for our second calls.  Otherwise
  211.  * it proceeds to re-verify that the head is on the right track.  This
  212.  * makes us miss the next sector.  It also means that all single
  213.  * sector read/write calls take ONE rev for each sector!!!!!!!!!  
  214.  *
  215.  *        UGLY!!!! UGLY!!!! UGLY!!!!!
  216.  *
  217.  * our_floprd(buf, filler, devno, sectno, trackno, sideno, count)
  218.  * our_flopwr(buf, filler, devno, sectno, trackno, sideno, count)
  219.  *
  220.  */
  221.  
  222. /*
  223.  * The following are hard addresses in the TOS ROM!
  224.  * 
  225.  * You are NEVER supposed to do this.  But since we know what we're
  226.  * doing ....
  227.  *
  228.  * values for original 11/20/85 roms
  229.  */
  230. #define change     0xfc1cbe
  231. #define floplock   0xfc1a34
  232. #define select     0xfc1c14
  233. #define go2track   0xfc1b7a
  234. #define setdmode   0xfc1cf6
  235. #define to_rom_r   0xfc15b4
  236. #define to_rom_w   0xfc16a8 
  237. /*
  238.  * values for blitter roms
  239.  */
  240. #define m_change   0xfc1ebe
  241. #define m_floplock 0xfc1c48
  242. #define m_select   0xfc1e14
  243. #define m_go2track 0xfc1d7a
  244. #define m_setdmode 0xfc1ef6
  245. #define m_to_rom_r 0xfc1798
  246. #define m_to_rom_w 0xfc1884
  247.  
  248. /* 
  249.  * declarations to allow inline asm outside of a func to work.
  250.  */
  251. extern our_floprd(), our_flopwr(), meg_floprd(), meg_flopwr();
  252.  
  253. /*
  254.  * The commented out lines are the WHOLE reason this code is
  255.  * duplicated here.  If they weren't in the ROM or if track stepping
  256.  * was handled intellegently this crap wouldn't be needed.
  257.  *
  258.  * These lines are from the floppy i/o code as previously published in
  259.  * STart in Dave's track dumper article.  (Issue #1)
  260.  *
  261.  * In order to keep things simple here we will supply two different
  262.  * pairs of these routines.  One for the ROM addresses in the old STs and
  263.  * one for the new ones.
  264.  */
  265. asm {
  266. our_floprd:
  267.     jsr       change        ; test for disk change
  268.     moveq     #0xf5, D0        ; set default error#
  269.     jsr       floplock        ; lock floppies, setup parameters
  270.     jsr       select        ; select drive,     setup registers
  271. ;  bsr       go2track            ; seek appropriate track (UGLY! -- dlm)
  272.     jmp       to_rom_r        ; and return to the REAL rom code.  -- dlm
  273.  
  274.  
  275. meg_floprd:
  276.     jsr       m_change              ; test for disk change
  277.     moveq     #0xf5, D0             ; set default error#
  278.     jsr       m_floplock            ; lock floppies, setup parameters
  279.     jsr       m_select              ; select drive,     setup registers
  280. ;  bsr       go2track                   ; seek appropriate track (UGLY! -- dlm)
  281.     jmp       m_to_rom_r            ; and return to the REAL rom code.  -- dlm
  282.  
  283.  
  284.  
  285. our_flopwr:
  286.     jsr       change              ; check for disk swap
  287.     moveq     #0xf6,D0            ; set default error number
  288.     jsr       floplock            ; lock floppies
  289.  
  290. ;
  291. ; If the boot sector is written to,
  292. ; set the media change mode to "unsure".
  293. ; (Kludge, kludge, kludge....)
  294.     move.w    0x9c6(A5),D0        ; sector 1
  295.     subq      #1,D0
  296.     or.w      0x9c4(A5),D0        ; track 0
  297.     or.w      0x9c8(A5),D0        ; side 0
  298.     bne       fwr1                ; if not boot sector, then OK
  299.     moveq     #2,D0               ; set media change mode to unsure
  300.     jsr       setdmode            ; (boy, is this /ugly/)
  301.  
  302. fwr1:
  303.     jsr       select              ; select drive
  304. ;    bsr       go2track            ; seek    (no, THIS is ugly) -- dlm
  305.  
  306.     jmp       to_rom_w            ; back to the REAL rom code -- dlm
  307.  
  308. meg_flopwr:
  309.     jsr       m_change            ; check for disk swap
  310.     moveq     #0xf6,D0            ; set default error number
  311.     jsr       m_floplock          ; lock floppies
  312.  
  313. ;
  314. ; If the boot sector is written to,
  315. ; set the media change mode to "unsure".
  316. ; (Kludge, kludge, kludge....)
  317.     move.w    0x9c6(A5),D0        ; sector 1
  318.     subq      #1,D0
  319.     or.w      0x9c4(A5),D0        ; track 0
  320.     or.w      0x9c8(A5),D0        ; side 0
  321.     bne       m_fwr1              ; if not boot sector, then OK
  322.     moveq     #2,D0               ; set media change mode to unsure
  323.     jsr       m_setdmode          ; (boy, is this /ugly/)
  324.  
  325. m_fwr1:
  326.     jsr       m_select            ; select drive
  327. ;    bsr       m_go2track             ; seek    (no, THIS is ugly) -- dlm
  328.  
  329.     jmp       m_to_rom_w          ; back to the REAL rom code -- dlm
  330. }
  331.  
  332. /*
  333.  * The Trans-Warp Drive version of rwabs.   It takes care of
  334.  * all the work involved in the floppy i/o.
  335.  */
  336. LONG
  337. trans_warp(rw, buf, count, recno, dev)
  338. LONG buf;
  339. WORD rw, count, recno, dev;
  340. {
  341.     LONG ret;
  342.     register struct dsb *p;
  343.     register WORD track, side, sect, cnt;
  344.     WORD oddflag;        /* 
  345.                       * indicates an oddbyte copy, requiring
  346.                       * a seperate buffer (floprd, flopwr only work
  347.                       * to a word aligned buffer), thus
  348.                       * indicates pre-write or post-read copy. 
  349.                       */
  350.     WORD modulus;        /* 
  351.                       * The # to divide the track by to find out
  352.                       * how to twist the readin process. 
  353.                       */
  354.     WORD last_track = -1; /* 
  355.                        * The last track we read. We don't use a
  356.                        * read-with-seek if we are on same track,
  357.                        * else reads to other side of same disk
  358.                        * lose a spin. 
  359.                        */
  360.     LONG bf;               /* working i/o buffer */
  361.     WORD skewer, counter;  /* starting sector & # to read on 2nd spin. */
  362.  
  363.         /* 9 sector skew data  */
  364.     static WORD skew[] = {1, 3, 5, 7};        /* start read sec    */
  365.     static WORD cnton2[] = { 0,  2,  4,  6};  /* count for 2nd rd, start at 1 */
  366.         /* 10 sector skew data */
  367.     static WORD skew10[] = {1, 3, 5, 7, 9};      /* which sec to start on */
  368.     static WORD cnt10[] = { 0,  2,  4,  6,  8};  /* cnt for 2nd spin */
  369.  
  370.     /* 
  371.      * All this takes some explaining, so go look at the article, which is
  372.      * why I WRITE these things, okay? 
  373.      */
  374.  
  375.     /* at this point the trap dispatcher has saved D3-D7/A3-A6 */
  376.     asm {
  377.         movea.l   saveA4(PC), A4      ; Megamax global variable pointer 
  378.     }
  379.  
  380.     /* first see if this call is for us or not */
  381.     if (dev >= 2) {  /* Pass the call thru to the system rwabs routine. */
  382.         return((*sys_rwabs)(rw, buf, count, recno, dev));
  383.     }
  384.  
  385.     /* we are wanted.  Dead or alive */
  386.     if (!*nflops)       
  387.         return (DRIVE_NOT_READY);     /* no disks (foolish person) */
  388.  
  389.     /*
  390.      *   If 'buf' is 0L, then set the media-change mode
  391.      *   on the dev to whatever 'count' is. This is a little known
  392.      *   hack to get rid of media changes. */
  393.      if (!buf) {
  394.          diskmode[dev] = count;
  395.          return (OK);
  396.      }
  397.  
  398.      /*
  399.       * If 'rw' allows media-change checking, then
  400.       * make sure the disk in the drive is the one we
  401.       * really want there.  If 'chkmedia' returns a
  402.       * hard error, return that hard error.  If 'chkmedia'
  403.       * discovers a media change, return that.
  404.       */
  405.      if (rw < 2 && (ret = (long)(*chkmedia)(dev)) != 0) {
  406.         if (ret == CHANGED)
  407.             ret = MEDIA_CHANGE;
  408.         return (ret);       /* frankly my dear, I don't give a damn */
  409.  
  410.                 /* 
  411.                  * Pun Alert:
  412.                  *  The preceding comment was a pun. 
  413.                  *  If you missed it, think of 
  414.                  *  Gone With the Wind. 
  415.                  */
  416.     }
  417.  
  418. /* Skew table logic:
  419.  *
  420.  *                 9-sector disks:
  421.  *  0: 123456789 123456789 123456789 123456789 123456789 123456789 123456789
  422.  *   *********
  423.  *  1: 123456789 123456789 123456789 123456789 123456789 123456789 123456789
  424.  *                 **********
  425.  *  2: 123456789 123456789 123456789 123456789 123456789 123456789 123456789
  426.  *                             ********** 
  427.  *  3: 123456789 123456789 123456789 123456789 123456789 123456789 123456789
  428.  *                                         *** ******
  429.  *  4: 123456789 123456789 123456789 123456789 123456789 123456789 123456789
  430.  *                                                        ********
  431.  *  5: 123456789 123456789 123456789 123456789 123456789 123456789 123456789
  432.  *
  433.  *   0: read 1-9, no other read.
  434.  *   1: read 3-9, then 1-2.
  435.  *   2: read 5-9, then 1-4.
  436.  *   3: read 7-9, then 1-6.
  437.  *   4: read 1-9, no other read.  (we drop an extra sector, but, big deal...)
  438.  *
  439.  * This info is in the skew and cnton2 arrays. Skew tells us the starting
  440.  * sector for the primary read. cnton2 tells us how many sectors, starting
  441.  * at 1, we read in the secondary read. If cnton2 is 0, then we have no
  442.  * secondary read.
  443.  * 
  444.  *                 10 sector disks:
  445.  *
  446.  *  0: 123456789A 123456789A 123456789A 123456789A 123456789A 123456789A 123456789A
  447.  *     **********
  448.  *  1: 123456789A 123456789A 123456789A 123456789A 123456789A 123456789A 123456789A
  449.  *                  ******** **
  450.  *  2: 123456789A 123456789A 123456789A 123456789A 123456789A 123456789A 123456789A
  451.  *                               ****** ****
  452.  *  3: 123456789A 123456789A 123456789A 123456789A 123456789A 123456789A 123456789A
  453.  *                                            **** ******
  454.  *  4: 123456789A 123456789A 123456789A 123456789A 123456789A 123456789A 123456789A
  455.  *                                                         ** ********
  456.  *  5: 123456789A 123456789A 123456789A 123456789A 123456789A 123456789A 123456789A
  457.  *                                                                       ********** 
  458.  *
  459.  *  0: read 1-A, no second.
  460.  *  1: read 3-A, then 1-2.
  461.  *  2: read 5-A, then 1-4.
  462.  *  3: read 7-A, then 1-6.
  463.  *  4: read 9-A, then 1-8.
  464.  *  5: read 1-A, no second.
  465.  *
  466.  * The skew10[] and cnt10[] arrays hold THIS information. We pick between
  467.  * these arrays, and whether to go by 5 (10 secs) or 4 (9 secs), based on
  468.  * info DOS gives us (p->dspt).
  469.  *
  470.  *
  471.  * 10 sector Twistered Disks, assuming normal 10-sec Transwarp done.
  472.  *
  473.  *  0: 123456789A 123456789A 123456789A 123456789A 123456789A 123456789A 123456789A
  474.  *     **********
  475.  *  1: 9A12345678 9A12345678 9A12345678 9A12345678 9A12345678 9A12345678 9A12345678 
  476.  *                    ****** ****
  477.  *  2: 789A123456 789A123456 789A123456 789A123456 789A123456 789A123456 789A123456 
  478.  *                                   ** ********
  479.  *  3: 56789A1234 56789A1234 56789A1234 56789A1234 56789A1234 56789A1234 56789A1234 
  480.  *                                                   ******** **
  481.  *  4: 3456789A12 56789A1234 56789A1234 56789A1234 56789A1234 56789A1234 56789A1234 
  482.  *                                                                ***********  
  483.  *  5: 123456789A 123456789A 123456789A 123456789A 123456789A 123456789A 123456789A
  484.  *                                                                          --> 1-A
  485.  *
  486.  * Hence, it just slows down Twister a bit (2 secs more per) - gives it
  487.  * 4 sectors to resync as opposed to 2, which is the minimum.
  488.  *
  489.  * Net effect is that twistered disks will run slightly slower under
  490.  * Transwarp than by themselves...but at least it isn't a large loss.
  491.  *
  492.  * Besides Twistered disks still run fast without Transwarp.
  493.  */
  494.  
  495.     p = &dsbtab[dev];              /* pointer to drive info table */
  496.  
  497.     oddflag = ((buf & 1) == 1);    /* odd address transfer? (slow if it is) */
  498.  
  499.     if (!p->dspc)                  /* "cannot happen"             */
  500.         p->dspt = p->dspc = 9;
  501.  
  502.     /*
  503.      * Read or write sectors.
  504.      * Optimize for multi-sector transfers
  505.      * (as much of a track as possible):
  506.      */
  507.     while (count) {
  508.         bf = (oddflag ? (long) diskbuf : buf);    /* choose a buffer */
  509.  
  510.         track = recno / p->dspc;      /* compute track# */
  511.  
  512.         sect = recno % p->dspc;       /* compute sector# */
  513.  
  514.         if (sect < p->dspt)
  515.             side = 0;                /* single-sided media */
  516.         else {                        /* two-sided media */
  517.             side = 1;
  518.             sect -= p->dspt;
  519.         } 
  520.  
  521.         if (oddflag) 
  522.             cnt = 1;                 /* unaligned: read 1 sector */
  523.         else if ((p->dspt - sect) < count)
  524.             cnt = p->dspt - sect;    /* rest of track */
  525.         else 
  526.             cnt = count;             /* part of track */
  527.  
  528.         ++sect;                       /* physical sector number */
  529.  
  530.         do {   /* loop while there is an error */
  531.             if (rw & 1) {                 /* write */
  532.                 if (bf != buf)  /* if odd aligned, get into even buffer. */
  533.                     bytecpy(buf, bf);
  534.  
  535.                 if (cnt == p->dspt && sect == 1) { /* whole track? */
  536.  
  537.                     /* Yup. So, pick modulus. 9 sector disks: 4. 10 sector disks: 5. */
  538.  
  539.                     modulus = track % (p->dspt == 9 ? 4 : 5);      
  540.  
  541.                     /* 
  542.                      * Pick off, for this track, the sector to start 
  543.                      * reading at in the primary pass, and the sector 
  544.                      * to read up to in the secondary pass. 
  545.                      */
  546.  
  547.                     if (p->dspt == 9) {          /* 9 sec  */
  548.                         skewer = skew[modulus];
  549.                         counter = cnton2[modulus]; 
  550.                     }
  551.                     else {                       /* 10 sec */
  552.                         skewer = skew10[modulus]; 
  553.                         counter = cnt10[modulus]; 
  554.                     }
  555.  
  556.                     /*
  557.                      * it also slows down from side to side on the
  558.                      * same track since Flopwr re-verfies even THEN!
  559.                      * 
  560.                      * our smart code doesn't do a seek if we are on the
  561.                      * same track (already verified).
  562.                      */
  563.  
  564.                     if (last_track == track) {  /* track hasn't changed */
  565.                         do_write(bf + (skewer-1) * 512, 0L, dev, skewer,  /* no seek */
  566.                             track, side, p->dspt - skewer + 1);
  567.                     }
  568.                     else {
  569.                         ret = Flopwr(bf + (skewer-1) * 512, 0L, dev, skewer, /* yes seek */
  570.                             track, side, p->dspt - skewer + 1);
  571.                     }
  572.  
  573.                     if (ret == 0 && counter)  /* two writes? */
  574.                         do_write(bf, 0L, dev, 1, track, side, counter); /* no seek */
  575.                 }
  576.                 else { /* partial track */
  577.                     ret = Flopwr(bf, 0L, dev, sect, track, side, cnt);
  578.                 }
  579.  
  580.                 last_track = track;  /* save it for next time through */
  581.  
  582.                 /* 
  583.                  * This handles the $%^$% read-after-write verify.
  584.                  * Should just ditch the %^&$%^& thing. 
  585.                  */
  586.  
  587.                 if (!ret && *fverify) {          /* verify */
  588.                     ret = Flopver(diskbuf, 0L, dev, sect, track, side, cnt);
  589.                     if (!ret && swapint(diskbuf))
  590.                         ret = BAD_SECTORS;
  591.                 }
  592.             }         /* end of write code */
  593.             else {    /* read */
  594.                 if (cnt == p->dspt && sect == 1) { /* whole track? */
  595.                     modulus = track % (p->dspt == 9 ? 4 : 5);      
  596.  
  597.                     if   (p->dspt == 9) {
  598.                         skewer = skew[modulus];
  599.                         counter = cnton2[modulus]; 
  600.                     }
  601.                     else {
  602.                         skewer = skew10[modulus];
  603.                         counter = cnt10[modulus];
  604.                     }
  605.  
  606.                     /* see the comment on flopwr above */
  607.  
  608.                     if (last_track == track) { /* probly second side read */
  609.                         do_read(bf + (skewer-1) * 512, 0L, dev, skewer, /* no seek*/
  610.                                     track, side, p->dspt - skewer + 1);
  611.                     }
  612.                     else {
  613.                         ret = Floprd(bf + (skewer-1) * 512, 0L, dev, skewer, /* yes seek */
  614.                                     track, side, p->dspt - skewer + 1);
  615.                     }
  616.  
  617.                     if (ret == 0 && counter) {  /* two reads? */
  618.                         do_read(bf, 0L, dev, 1, track, side, counter);/* no seek */
  619.                     }
  620.                 } 
  621.                 else { /* normal read */
  622.                     ret = Floprd(bf, 0L, dev, sect, track, side, cnt); /* seek */
  623.                 }
  624.  
  625.                 last_track = track; /* save current track */
  626.  
  627.                 if (bf != buf)      /* unaligned? */
  628.                     bytecpy(bf, buf);
  629.             }    /* end of read code */
  630.  
  631.             /*
  632.              * If an error has occured pass the code thru to
  633.              * the critical error handler.  (Normally this is
  634.              * the cute GEM alert message that says RETRY or CANCEL.)
  635.              */
  636.             if (ret < 0) {
  637.                 ret = (**critic)((WORD)ret, dev);
  638.                 if (rw < 2 && ret == CRITICAL_RETRY && (*chkmedia)(dev) == CHANGED)
  639.                     ret = MEDIA_CHANGE;
  640.                 last_track = 99;   /* force a real seek next time */
  641.             }
  642.         } while (ret == CRITICAL_RETRY);
  643.  
  644.         if (ret < 0) 
  645.             return (ret);
  646.  
  647.         buf += ((long)cnt << 9);      /* advance DMA pointer */
  648.         recno += cnt;                 /* bump record number */
  649.         count -= cnt;                 /* decrement count */
  650.     }
  651.  
  652.     return (OK);             
  653. }
  654.  
  655. void
  656. super_stuff()
  657. /*
  658.  * read the default sysrwabs vector; store it; plug in our new one.
  659.  *
  660.  * also make sure we get real resets instead of fake ones and
  661.  * disable write with verify.  other programs (DAs and TSRs) may already
  662.  * do that, but it doesn't hurt to be sure.
  663.  *
  664.  * And finally, check the build date of the OS ROMs.  We don't want to 
  665.  * go jumping off to never-never land do we.
  666.  */
  667. {
  668.     asm {
  669.         /* do this stuff always */
  670.         clr.w   0x444       ; flopver
  671.         clr.l   0x420       ; memvalid
  672.         clr.l   0x43a       ; memval2
  673.  
  674.         cmpi.l  #BUILDDATE, DATEADR
  675.         beq     old_rom
  676.  
  677.         cmpi.l    #MEGDATE, DATEADR
  678.         beq    new_rom
  679.  
  680.         clr.w   all_cool(A4)     ; wrong ROM!  Oh s***!
  681.         bra     bad_rom
  682.  
  683.     }
  684.  
  685. old_rom:
  686.     chkmedia   = (L_FUNC)        old_chkm;
  687.     dsbtab     = (struct dsb *)    old_dsbtab;
  688.     diskmode   = (BYTE *)        old_diskm;
  689.     diskbuf    = (BYTE *)        old_diskbuf;
  690.     newer_roms =              FALSE;
  691.     goto good_rom;
  692.  
  693. new_rom:
  694.     chkmedia   = (L_FUNC)        new_chkm;
  695.      dsbtab     = (struct dsb *)    new_dsbtab;
  696.      diskmode   = (BYTE *)        new_diskm;
  697.      diskbuf    = (BYTE *)        new_diskbuf;
  698.      newer_roms =            TRUE;
  699.  
  700.         /* falls thru here */
  701.  
  702.         /* aaaaaaaaaaaaahhhhhhhhhhhhhhhhhh!!!!! */
  703.  
  704.         /*   S  P  L  A  T !!!!!! */
  705.  
  706. good_rom:
  707.  
  708.     /* hook up the vectors to the new code */
  709.  
  710.  
  711.     /* be sure to use REALLY strong wire in the hook ups */
  712.  
  713.     sys_rwabs = *rwvect;
  714.     *rwvect   = trans_warp;
  715.     all_cool  = TRUE;
  716.  
  717. bad_rom:       ;
  718. }
  719.  
  720. /* 
  721.  * base page data. We need this to calculcate amount to keep resident. 
  722.  */
  723. #define  codelen 12       /* Code segment length */
  724. #define  datalen 20       /* Data segment length */
  725. #define  bsslen  28       /* Bss  segment length */
  726. extern char *_base;       /* pointer to base page */
  727.  
  728. main()
  729. {
  730. #if LOADADR
  731.     LONG start_l, end_l; /* passed from base page, in assy, to C for printf */
  732.  
  733.     asm {
  734.         movea.l   _base(A4), A0       ; get base page indexes addr
  735.         move.l    A0, start_l(A6)     ; save start of this code to disp
  736.         move.l    A0, D0              ; set start
  737.         add.l     codelen(A0),D0
  738.         add.l     datalen(A0),D0
  739.         add.l     bsslen(A0),D0
  740.         add.l     #256, D0            ; D0=basepage+textlen+datalen+bsslen 
  741.         move.l    D0,end_l(A6)        ; save end of this code to  disp
  742.     }
  743. #endif
  744.  
  745.  
  746.     /*
  747.      * first get the base address for the global variables so our rwabs can
  748.      * use them.
  749.      *
  750.      * this is just about the only disadvantage to using Megamax for
  751.      * this kind of stuff.  And it is pretty trivial to get around.
  752.      *
  753.      */
  754.     asm {
  755.         lea     saveA4(PC), A0
  756.         move.l  A4, (A0)
  757.     }
  758.  
  759.     /* 
  760.      * find the current rwabs routine and do other super stuff
  761.      */
  762.     Supexec(super_stuff);
  763.  
  764.     /* 
  765.      * now lets see if all is cool with the ROM.  If not say so and
  766.      * run away to mommy.
  767.      */
  768.     if (!all_cool) {
  769.         puts("Trans-Warp Drive not loaded.\r\nWrong TOS ROM installed.\r\n");
  770.         Pterm(1);      /* back to mother */
  771.     }
  772.  
  773.     /* 
  774.      *
  775.      * Will tonight's mystory guest please sign in ...
  776.      */
  777.     puts("\r\n**********************************************\r\n");
  778.     puts("*                                            *\r\n");
  779.     puts("*       Trans-Warp Drive, Version 5.10       *\r\n");
  780.     puts("* Copyright 1987,1988 Dan Moore & Dave Small *\r\n");
  781.     puts("*    New, Improved and Mega Compatible!!!!   *\r\n");
  782.     puts("*       Resets foxed. Floppy verify off.     *\r\n");
  783.     puts("*                                            *\r\n");
  784. #if LOADADR
  785.     puts("*  RAM locations used:                       *\r\n");
  786.     printf("*  Start: $%06lx  End: $%06lx             *\n",start_l,end_l);
  787. #endif
  788.     puts("**********************************************\r\n");
  789.  
  790.  
  791.     /* 
  792.      * do a ptermres to return to system. We pass it the # of
  793.      * bytes we wanna retain, so add up our usage, add 256 for the
  794.      * base page, pray, and do it. 
  795.      */
  796.  
  797.     asm {
  798.         movea.l   _base(A4), A0
  799.         move.l    codelen(A0), D0
  800.         add.l     datalen(A0), D0
  801.         add.l     bsslen(A0), D0
  802.         add.l     #256, D0          ; D0=basepage+textlen+datalen+bsslen 
  803.  
  804.         /* Actual ptermres (absolutely amazing, a genuine ptermres!) */
  805.         move.w    #0, -(A7)         ; returned status (ok)
  806.         move.l    D0, -(A7)         ; keep this # of bytes
  807.         move.w    #0x31, -(A7)      ; ptermres command
  808.         trap #1                     ; call gemdos
  809.     }
  810. }
  811.